
var Ring = {
    /**
     * 振铃
     */
    startRingTone: function () {
        let play = document.getElementById("ringtone").play();


    },
    /**
     * 停止振铃
     */
    stopRingTone: function () {
        document.getElementById("ringtone").pause();
    },

    startRingbackTone: function () {
        let play = document.getElementById("ringbacktone").play();
    },
    stopRingbackTone: function () {
        document.getElementById("ringbacktone").pause();
    }

};

var CurrentSession = {
    canHold: false,
    ringing: false,
    session: null,
    originator: null
};

// 外呼session
var outgoingSession = null;

// 来电session
var incomingSession = null;


var startCall = document.getElementById('startCall');
var endCall = document.getElementById('endCall');
var transfer = document.getElementById('transfer');
var hold = document.getElementById('hold');
var unhold = document.getElementById('unhold');
var sendMessage = document.getElementById('sendMessage');
var mute = document.getElementById('mute');
var unmute = document.getElementById('unmute');
var remoteVideo = document.getElementById('remoteVideo');
var localVideo = document.getElementById('localVideo');
var options = {
    // 'eventHandlers'    : eventHandlers,
    'mediaConstraints': {'audio': true, 'video': false},
    'extraHeaders': [],
    'sessionTimersExpires': 180
};
var localStream = null;


// Create our JsSIP instance and run it:
var socket = new JsSIP.WebSocketInterface('wss://119.23.191.208:7443');
var configuration = {
    sockets: [socket],
    uri: 'sip:admin2@119.23.191.208:5066',
    authorization_user: 'admin2',
    password: 'admin2',
    // WebSocket重新连接调度之间的最大间隔(秒)。默认值是30。
    connection_recovery_max_interval: 60,
    // WebSocket重新连接尝试之间的最小间隔(秒)。默认值是2。
    connection_recovery_min_interval: 4,
    // String 注册到fs显示的url
    contact_uri: 'sip:admin2@119.23.191.208:5066;transport=wss',
    // 外显
    display_name: '10086',
    // 来电后,120秒内未接听,将会拒绝.默认60s
    no_answer_timeout: 120,
    // 会话计时器,默认true
    session_timers: false,
    // 用于刷新会话计时器的SIP方法。有效值是UPDATE或INVITE。默认值是UPDATE。
    session_timers_refresh_method: 'invite',
    // 是否应该在启动时自动注册.默认true
    register: true,
    // 注册过期时间(秒) 默认值是600。
    register_expires: 300,
    //  User-Agent header中的值,默认是JsSIP
    user_agent: "bang",
    registrar_server: "sip:119.23.191.208:5066"
};

var ua = new JsSIP.UA(configuration);

// 连接到信令服务器，并在以前停止时恢复以前的状态。对于新的开始，如果UA配置中的register参数设置为true，则使用SIP域注册。
ua.start();
// 保存当前注册状态，并在优雅地取消注册和终止活动会话(如果有活动会话)之后断开与信令服务器的连接。
// ua.stop();

// 注册到服务器 如果设置了register:true,则会自动注册,不需要调用此方法
// ua.register();

// 取消注册
// ua.unregister({
//     all: true
// });

if (ua.isRegistered()) {
    alert("注册成功");
} else {
    ua.register();
}

if (ua.isConnected()) {
    alert("the transport is connected");
}

ua.on('connecting', function (data) {
    console.error("connecting 正在建立连接 .........");
    let dataSocket = data.socket;
    let attempts = data.attempts;
    console.log(dataSocket);
    console.log(attempts);
    console.error("connecting 正在建立连接 .........");
});

ua.on('connected', function (data) {
    console.error("connected 已经建立连接 .........");
    let dataSocket = data.socket;
    console.log(dataSocket);
    console.error("connected 已经建立连接 .........");
});

ua.on('disconnected', function (data) {
    console.error("disconnected 断开连接 .........");
    let dataSocket = data.socket;
    let error = data.error;
    let code = data.code;
    let reason = data.reason;
    console.log(data);
    console.error("disconnected 断开连接 .........");
});

ua.on('registered', function (data) {
    console.error("registered 注册成功 .........");
    let response = data.response;
    console.log(response);
    console.error("registered 注册成功 .........");

});

ua.on('unregistered', function (data) {
    console.error("unregistered 取消注册 .........");
    let response = data.response;
    let cause = data.cause;
    console.log(data);
    console.error("unregistered 取消注册 .........");
});

ua.on('registrationFailed', function (data) {
    console.error("registrationFailed 注册失败 .........");
    let response = data.response;
    let cause = data.cause;
    console.log(data);
    console.error("registrationFailed 注册失败 .........");
});


var globalSession = null;

// 新来会话
ua.on('newRTCSession', function (data) {

    console.log('新来会话 onNewRTCSession: ', data);

    //  remote: 新会话由远程对等点生成。
    //  local: 新会话由本地用户生成。
    let originator = data.originator;
    // session实例
    let session = data.session;
    //  remote:JsSIP.IncomingRequest实例. 接收到的INVITE请求的IncomingRequest实例。
    //  local: JsSIP.OutgoingRequest实例. 发出邀请请求的OutgoingRequest实例。
    let request = data.request;
    globalSession = session;
    if (CurrentSession.session != null&&CurrentSession.session.direction==='incoming') {
        session.terminate({
            'status_code'   : 486,
            'reason_phrase' : 'Busy Here'
        });
        return;
    }
    // 赋值
    CurrentSession.session = session;
    CurrentSession.originator = originator;



    // 注册事件
    // session.on('peerconnection', function (data) {
    //     let peerconnection1 = data.peerconnection;
    //     console.error('onPeerconnection - ', peerconnection1);
    //     console.error('CurrentSession.session - ', CurrentSession.session);
    //
    //
    //     // Handle local stream
    //     if (peerconnection1.getLocalStreams()[0]){
    //         // Clone local stream
    //         // Display local stream
    //         localVideo.srcObject =peerconnection1.getLocalStreams()[0].clone();
    //     }
    //
    //     peerconnection1.onaddstream = function (ev) {
    //         console.error('onaddstream from remote - ', ev);
    //         handleRemoteStream(event.stream);
    //     };
    //
    // });

    session.on('accepted', function (data) {
        Ring.stopRingTone();

        console.error('onAccepted - ', data);
        console.error('CurrentSession.session - ', CurrentSession.session);

        CurrentSession.ringing = false;
        CurrentSession.canHold = true;
        CurrentSession.session = this;

        if (data.originator == 'remote') {

            console.error("accepted setCurrentSession - ", CurrentSession.session);
            incomingSession = null;

        }else{
            let connection = CurrentSession.session.connection;
            console.error("accepted setCurrentSession - connection", connection);

            localStream = connection.getLocalStreams()[0];
            // Handle local stream
            if (localStream) {
                // Clone local stream
                // Display local stream
                localVideo.srcObject = localStream.clone();
                localVideo.volume = 1;
            }
            console.error("localStream", connection.getLocalStreams());


            const remoteStream = connection.getRemoteStreams()[0];
            // If incoming all we already have the remote stream
            if (remoteStream) {
                handleRemoteStream(remoteStream);
            }

            connection.addEventListener('addstream', (event) => {
                console.info('peerconnection "addstream" event');
            handleRemoteStream(event.stream);
        });
        }
    });


    session.on('confirmed', function (data) {
        console.error('onConfirmed - ', data);
        console.error('CurrentSession.session - ', CurrentSession.session);
        CurrentSession.session = this;
        if (data.originator == 'remote') {
            console.error("setCurrentSession - ", CurrentSession.session);
            incomingSession = null;
        } else if (data.originator == 'local') {
            Ring.stopRingbackTone();
        }

    });


    session.on('progress', function (data) {
        console.error('CurrentSession.session - ', CurrentSession.session);
        CurrentSession.ringing = true;

        console.error('onProgress - ', data.originator);
        if (data.originator == 'remote') {
            console.error('onProgress, response - ', data.response);
        }
    });


    session.on('ended', function (data) {
        Ring.stopRingTone();
        console.error('CurrentSession.session - ', CurrentSession.session);
        CurrentSession.ringing = false;
        CurrentSession.canHold = false;
        CurrentSession.session = null;
        CurrentSession.originator = null;


        let originator = data.originator;
        let message = data.message;
        let cause = data.cause;

        console.error('ended -originator ', originator);
        console.error('ended, message - ', message);
        console.error('ended, cause - ', cause);


    });


    session.on('failed', function (data) {
        Ring.stopRingTone();
        console.error('CurrentSession.session - ', CurrentSession.session);
        CurrentSession.ringing = false;
        CurrentSession.canHold = false;
        CurrentSession.session = null;
        CurrentSession.originator = null;


        let originator = data.originator;
        let message = data.message;
        let cause = data.cause;
        console.error('failed -originator ', originator);
        console.error('failed, message - ', message);
        console.error('failed, cause - ', cause);
    });


    // 处理session
    if (originator == 'remote') {
        //incoming call
        console.error("incomingSession, answer the call");
        Ring.startRingTone(); //来电振铃
        let url = session.remote_identity.uri.toString() + "来电了，是否接听";
        let toString = session.remote_identity.display_name.toString();

        let callsource = request.getHeader('X-Call_Source');
        let flowdata = request.getHeader('X-Flowdata');
        let recordFile = request.getHeader('X-Record_File');
        $(".incoming").html(url);
        $("#myModal").modal('show');
        incomingSession = session;

    } else {
        // outbound call 外呼
        console.error("outgoingSession");
        outgoingSession = session;
        outgoingSession.on('connecting', function (data) {
            console.error('onConnecting - ', data.request);
            CurrentSession.session = outgoingSession;
            outgoingSession = null;
        });
    }


    let peerconnection = session.connection;
    if (peerconnection != null) {
        const localStream = peerconnection.getLocalStreams()[0];
        const remoteStream = peerconnection.getRemoteStreams()[0];
        // Handle local stream
        if (localStream) {
            // Clone local stream
            // Display local stream
            localVideo.srcObject = localStream.clone();
            localVideo.volume = 1;

        }
        // If incoming all we already have the remote stream
        if (remoteStream) {
            handleRemoteStream(remoteStream);
        }
        peerconnection.addEventListener('addstream', (event) => {
            console.info('peerconnection "addstream" event');
        handleRemoteStream(event.stream);
    });
    }


});


// 新的sip消息
ua.on('newMessage', function (data) {
    console.error("newMessage 新的sip消息 .........");
    //  remote: 新会话由远程对等点生成。
    //  local: 新会话由本地用户生成。
    let originator = data.originator;
    // JsSIP.Message 实例
    let message = data.message;
    //  remote:JsSIP.IncomingRequest实例. 接收到的MESSAGE请求的IncomingRequest实例。
    //  local: JsSIP.OutgoingRequest实例. 发出MESSAGE请求的OutgoingRequest实例。
    let request = data.request;

    if (originator === 'remote') {
        // 接收消息
        message.accept();
    }
    console.error(data);
    console.error("newMessage 新的sip消息 .........");
});

// sipEvent
ua.on('sipEvent', function (data) {
    console.error("sipEvent 新的sipEvent .........");
    let event = data.event;
    // 接收到的通知请求的IncomingRequest实例。
    let request = data.request;
    console.error(event);
    console.error(request);
});


/**
 *  绑定方法
 * @param obj 要绑定事件的元素
 * @param ev 绑定的事件
 * @param fn  绑定事件的函数
 */
function bindEvent(obj, ev, fn) {
    if (obj.attachEvent) {
        obj.attachEvent("on" + ev, fn);
    }
    else {
        obj.addEventListener(ev, fn, false);
    }
}

/**
 *  发送DTMF
 * @param num 按键
 */
function sendDtmf(num) {
    if (CurrentSession.session==null) {
        alert("未建立会话,无法发送DTMF");
        return;
    }
    let options = {
        'duration': 160,
        'interToneGap': 1200,
        'extraHeaders': ['X-Foo: foo', 'X-Bar: bar']
    };
    CurrentSession.session.dtmf(num, options);
}

/**
 * 拨打电话
 */
bindEvent(startCall, 'click', function () {

    var number = document.getElementById("number").value;
    let extraHeaders = [];
    let contact = "sofia/internal/%s@192.168.0.250:5117";
    let replacedContact = contact.replace("%s", number);
    let temp="{origination_caller_id_number=18913825651}sofia/internal/18021411953@117.89.51.179:29679"
    extraHeaders.push("X-ReContact:" + temp);

    options.extraHeaders = extraHeaders;
    //创建一个新的出站（用户代理客户端）会话
    number = "call_" + number;
    ua.call(number, options);

    //开始嘟嘟嘟
    Ring.startRingbackTone();
});




var seatCall = document.getElementById('seatCall');


// 坐席之间呼叫
bindEvent(seatCall, 'click', function () {
    let number = document.getElementById("seat").value;
    //创建一个新的出站（用户代理客户端）会话
    number = "ttest" + number;
    ua.call(number, options);
});


//挂断事件
bindEvent(endCall, 'click', function () {
    let options = {
        extraHeaders: ["", "", ""], // Array of Strings with extra SIP headers for the MESSAGE request.
        status_code: "600", //  Number between 300 and 699 representing the SIP response code.
        reason_phrase: "bye", // 表示SIP原因短语的字符串。
        body: "body", //表示SIP消息体的字符串(如果设置了此参数，则必须在extraHeader字段中设置相应的Content-Type头字段)。
    };
    // ua.terminateSessions(options);
    ua.terminateSessions();
});


//电话转移盲转
bindEvent(transfer, 'click', function () {
    if (!CurrentSession.session) {
        return;
    }
    let number = document.getElementById("number").value;
    CurrentSession.session.refer(number, {
        eventHandlers: {
            requestSucceeded: function (data) {
                console.log("refer --------> requestSucceeded response", data.response);
            },
            requestFailed: function (data) {
                console.log("refer --------> requestFailed response", data.response, "cause", data.cause);
            },
            trying: function (data) {
                console.log("refer --------> trying request", data.request, "status_line", data.status_line);
            },
            failed: function (data) {
                console.log("refer --------> failed request", data.request, "status_line", data.status_line);
            },
            progress: function (data) {
                console.log("refer --------> progress request", data.request, "status_line", data.status_line);
            },
            accepted: function (data) {
                console.log("refer --------> accepted request", data.request, "status_line", data.status_line);
            }
        }
    });
});


//电话保持
bindEvent(hold, 'click', function () {
    if (!CurrentSession.session) {
        return;
    }
    if (CurrentSession.canHold) {
        CurrentSession.session.hold({useUpdate: false});
    }
});


//恢复电话保持
bindEvent(unhold, 'click', function () {
    if (!CurrentSession.session) {
        return;
    }
    if (CurrentSession.canHold) {
        CurrentSession.session.unhold({useUpdate: false});
    }

});

//发送消息
bindEvent(sendMessage, 'click', function () {
    // Sends a new message
    let eventHandlers = {
        'succeeded': function (data) {
            console.error("succeeded send msg ");
            console.error(data);
        },
        'failed': function (data) {
            console.error("failed send msg ");
            console.error(data);
        }
    };

    let options = {
        'eventHandlers': eventHandlers
    };
    let message = sendMessage.innerText;

    ua.sendMessage('sip:1012@192.168.0.108:50583', message, options);

});

// 静音
bindEvent(mute, 'click', function () {
    if (!CurrentSession.session) {
        console.warn("No session to toggle mute");
        return;
    }
    CurrentSession.session.mute({
        audio: true,
        video: true
    });

});

// 解除静音
bindEvent(unmute, 'click', function () {
    if (!CurrentSession.session) {
        console.warn("No session to toggle mute");
        return;
    }
    CurrentSession.session.unmute({
        audio: true,
        video: true
    });

});

// 接听电话
bindEvent(document.getElementById('acceptCall'), 'click', function () {
    if (null == CurrentSession.session) {
        return;
    }
    if (CurrentSession.originator=='remote') {
        CurrentSession.session.answer({
            'mediaConstraints': {
                'audio': true,
                'video': false,
            },
            'mediaStream': localStream
        });
    }

});

// 拒绝电话
bindEvent(document.getElementById('rejectCall'), 'click', function () {
    if (null == CurrentSession.session) {
        return;
    }
    if (CurrentSession.originator=='remote') {
        // 拒绝来电
        CurrentSession.session.terminate();
    }
});


bindEvent(document.getElementById('unregister'), 'click', function () {
    ua.unregister({all: true});

});

bindEvent(document.getElementById('register'), 'click', function () {
    ua.register();

});


/**
 *  JSSIP处理远程媒体
 * @param stream
 */
function handleRemoteStream(stream) {
    // Display remote stream
    remoteVideo.srcObject = stream;

    stream.addEventListener('addtrack', (event) => {
        const track = event.track;

    if (remoteVideo.srcObject !== stream)
        return;


    // Refresh remote video
    remoteVideo.srcObject = stream;
    track.addEventListener('ended', () => {

    });
});

    stream.addEventListener('removetrack', () => {
        if (remoteVideo.srcObject !== stream)
    return;
    // Refresh remote video
    remoteVideo.srcObject = stream;

});
}

// 监控页面刷新
window.onbeforeunload = function (event) {
    event.returnValue = "页面刷新或关闭...";
    return "页面刷新或关闭";
};

// 页面关闭时挂掉所有电话
window.onunload = function () {
    if (ua != null) {
        console.error("关闭session");
        localStorage.setItem("store", "执行关闭会话 ua");
        ua.terminateSessions();
    } else if (CurrentSession.session != null) {
        console.error("关闭会话");
        localStorage.setItem("store", "执行关闭会话 CurrentSession.session");
        CurrentSession.session.terminate();
    }
};
